// @ts-nocheck

export const types = [
  "number",
  "string",
  "boolean",
  "array",
  "null",
  "undefined",
  "regexp",
  "function",
];
const publicPath = "my-demo";

export const type = (arg: any) => {
  const s = Object.prototype.toString.call(arg);
  const r = /^\[\w+\s(\w+)\]$/.exec(s) || [];
  return r[1].toLowerCase();
};
const ExtKeys = ["this"];
export const expres = (s: string, ctx: any = {}) => {
  try {
    const keys = Object.keys(ctx).filter((k) => !ExtKeys.includes(k));
    const vals = keys.map((k) => ctx[k]);
    const str = "return " + s;
    return new Function(...keys, str)(...vals);
  } catch (e) {
    console.error("====表达式解析异常！=====", e);
  }
  return undefined;
};

// const JSON
export const json2str = (v: any) => {
  try {
    if (typeof v == "function") {
      return "{FUNCTION}" + String(v);
    }
    return v;
  } catch (error) {
    console.error(error);
  }
};

export const json2source = (v: string) => {
  if (/^\{FUNCTION\}/.test(v)) {
    return new Function("return " + v.replace("{FUNCTION}", ""));
  }
  return v;
};

// 序列化
export const serialize = (v: any) => {
  switch (type(v)) {
    case "array":
      return JSON.stringify(v, (k, v) => json2str(v));
    case "object":
      return JSON.stringify(v, (k, v) => json2str(v));
    case "undefined":
      return "undefined";
    case "null":
      return "null";
    case "function":
      return String(v);
    case "boolean":
      return String(v);
    case "regexp":
      return String(v);
  }
  return v;
};
// 反序列化
export const unserialize = (s: string, t: string) => {
  switch (t) {
    case "array":
      return JSON.parse(s, (k, v) => json2source(v));
    case "object":
      return JSON.parse(s, (k, v) => json2source(v));
    case "undefined":
      return undefined;
    case "null":
      return null;
    case "function":
      return new Function("return " + s);
    case "boolean":
      return s == "true" ? true : false;
    case "regexp":
      return new RegExp(s.slice(1, -1));
  }
  return s;
};

// localstorage 保存数据
export const saveLocal = (key: string, val: any) => {
  const t = type(val);
  const v = serialize(val);

  const c = {
    time: new Date().getTime(),
    type: t,
    value: v,
  };
  localStorage.setItem(key, JSON.stringify(c));
};
// 取出数据
export const getLocal = (key: string, source = false) => {
  const s = localStorage.getItem(key);
  if (s && /^{/.test(s)) {
    const c = JSON.parse(s);
    c.value = unserialize(c.value, c.type);
    //
    if (source) {
      return c;
    }
    return c.value;
  }
  return undefined;
};

//
export const modelLocalKey = "PAGE_MODEL_DATA";
export const saveModelData = (md: any) => {
  const key = modelLocalKey;
  saveLocal(key, md);
};

export const getModelData = async () => {
  const key = modelLocalKey;
  const res = getLocal(key);
  // if(res){
  //   return res;
  // }
  return await loadModelJson();
};

export const loadModelJson = async () => {
  const prefix = publicPath + "/modules/";
  const p = prefix + "index.json";
  const t = await loadJson(p);
  if (!t) return;
  const ds = await Promise.all(
    t.map((n: string) => loadJson(prefix + n + ".json"))
  );
  const data = Object.fromEntries(ds.map((d) => [d.key, d]));
  saveModelData(data);
  //
  return data;
};

//
import axios from "axios";
export const loadJson = async (path: string): Promise<any> => {
  const url = "/" + path;
  try {
    const res = await axios({ url, method: "get" });
    return res.data;
  } catch (error) {
    console.error(" === json load error === ", error);
  }
  return undefined;
};

//
const pageLocalKeyPrefix = "PAGES_DATA_KEY_";
export const loadPageJson = async (name: string) => {
  const path = publicPath + "/pages/" + name + ".json";
  const d = await loadJson(path);
  savePageJson(name, d);
  return d;
};

export const getPageData = async (name: string) => {
  const k = pageLocalKeyPrefix + name;
  const t = getLocal(k);
  if (t) {
    return t;
  }
  return await loadPageJson(name);
};

export const savePageJson = async (name: string, data: any) => {
  const k = pageLocalKeyPrefix + name;
  saveLocal(k, data);
};
const configFormPrefix = "formconfig";
export const loadConfigJson = async () => {
  const u = publicPath + "/" + configFormPrefix + "/";
  const ns = ["model", "page", "setting"];
  //
  const [m, p, s] = await Promise.all(ns.map((n) => loadJson(u + n + ".json")));
  //
  return { model: m, page: p, setting: s };
};

const pageLocalKey = "LOCALE_PAGE_LIST_KEY";
export const savePageList = (data: any) => {
  saveLocal(pageLocalKey, data);
  data.forEach((d: any) => {
    savePageJson(d.name, d);
  });
};

export const loadPageList = async () => {
  const ip = publicPath + "/pages/index.json";
  const ns = (await loadJson(ip)) || [];
  const list = await Promise.all(
    ns.map((n: string) => loadJson(`${publicPath}/pages/${n}.json`))
  );
  //
  if (list.length > 0) {
    return list;
  }
  return [];
};

export const getPageList = async () => {
  const t = getLocal(pageLocalKey);
  if (t) {
    return t;
  }

  return await loadPageList();
};

export const downloadBlob = (blob: Blob, name: string) => {
  const url = URL.createObjectURL(blob);
  downloadFromUrl(url, name);
};

export const downloadFromUrl = (url: string, name: string) => {
  const ea = document.createElement("a");
  ea.href = url;
  ea.download = name; //file.name
  ea.style.display = "none";
  ea.click();
};

// 图片转 base64
export const img2base64 = (fileBlob: Blob, fileType: string) => {
  return new Promise((resolve, reject) => {
    const imgurl = URL.createObjectURL(fileBlob);
    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d");
    const img = new Image();
    img.src = imgurl;
    img.onload = () => {
      canvas.height = img.height;
      canvas.width = img.width;
      ctx?.drawImage(img, 0, 0, img.width, img.height);
      const dataURL = canvas.toDataURL(fileType, 1); //获取Base64编码
      resolve(dataURL);
    };
    img.onerror = () => {
      reject();
    };
  });
};

// 修改 页面 title logo
export const resetWebBaseInfo = (data: Record<string, any> = {}) => {};

// 搜索高亮
export const searchHightlight = (
  cls: string,
  str = "",
  name = cls
) => {
  const Css: any = CSS;
  Css.highlights.clear();
  if (!Css.highlights || !str || str.trim().length == 0) {
    return;
  }
  //
  const s = str.trim().toLowerCase();
  const sl = s.length;
  const els = document.getElementsByClassName(cls);
  const ranges = [];
  const allNodes = [];
  for(const e of els){
    const treeWalker = document.createTreeWalker(e, NodeFilter.SHOW_TEXT);
    let currentNode = treeWalker.nextNode();
    while (currentNode) {
      allNodes.push(currentNode);
      currentNode = treeWalker.nextNode();
    }
  }
  for (const e of allNodes) {
    // 创建 createTreeWalker 迭代器，用于遍历文本节点，保存到一个数组
    const t = e.textContent?.toLowerCase() || "";
    if (!t) {
      continue;
    }
    const ins = [];
    let st = 0;
    while (st < t.length) {
      const i = t.indexOf(s, st);
      if (i == -1) break;
      ins.push(i);
      st = i + sl;
    }
    if (ins.length == 0) {
      continue;
    }
    ranges.push(
      ...ins.map((i) => {
        const range = new Range();
        range.setStart(e, i);
        range.setEnd(e, i + sl);
        return range;
      })
    );
  }
  //
  console.log('=========',ranges)
  // @ts-ignore 创建高亮对象
  const res = new Highlight(...ranges);
  // 注册高亮
  Css.highlights.set(name, res);
};

import {get} from "lodash-es"
export const groupArray = (arr:any[],fun:((d:any,i:number) => string) | string = '') => {
  const l = arr.length;
  const res = new Map<string,any[]>()
  for(let i = 0;i < l;i++){
    const d = arr[i];
    const key = typeof d === 'function' ? fun(d) : get(d,fun) ;
    if(!key){
      continue ;
    }
    if(!res.has(key)){
      res.set(key,[])
    }
    res.get(key).push(d)
  }

  return Array.from(res);
}

export const tryFn = (fn:() => any,title:string = "call error") => {
  try {
    fn();
  } catch (error) {
    console.log(title,'===========>',error)
  }
}